use bytes::Bytes;
use log::{info};
use tokio::sync::mpsc::{UnboundedSender};
use tokio::sync::oneshot::Sender;
use rpc::{ChannelId, RpcResult};
use rpc::connection_manager::event::{ConnectionEvent, ConnectionManageable, ResponseData, WriteData};
use crate::connection_manager::ServerConnectionManager;

#[derive(Debug)]
pub enum ConnectionMessage {

    /// 掉线
    Disconnection(ChannelId),

    Write(WriteData),

    NewConnection{
        channel_id: ChannelId,
        sender: UnboundedSender<Bytes>,
        recv_sender: Sender<bool>
    },

    Response(ResponseData),
}

impl ConnectionEvent for ConnectionMessage {

    fn handle(self, manager: &mut dyn ConnectionManageable) -> RpcResult<()> {
        manager.handle_event(Box::new(self));
        Ok(())
    }
}

impl ConnectionMessage {

    pub fn handle_event(self, manager: &mut ServerConnectionManager) {
        match self {
            ConnectionMessage::Disconnection(id) => {
                manager.remove_connection(id);
            }
            ConnectionMessage::Write(data) => {
                let WriteData{channel_id, local_seq, data, has_response, sender} = data;
                info!("router_service write data id: {:?}, local_seq: {:?}, length: {}", channel_id, local_seq, data.len());
                match sender {
                    None => {
                        let channel = manager.sender_by_channel_id.get(&channel_id).clone().unwrap();
                        channel.send(Bytes::from(data)).ok();
                    }
                    Some(sender) => {
                        if has_response {
                            manager.add_response_data(local_seq, sender);
                        }
                        let channel_sender = manager.sender_by_channel_id.get(&channel_id).clone().unwrap();
                        channel_sender.send(Bytes::from(data)).ok();
                    }
                }

            }
            ConnectionMessage::NewConnection { channel_id, sender, recv_sender: recev_sender } => {
                info!("New connection");
                manager.add_connection(channel_id, sender.clone());
                recev_sender.send(true).ok();
            }
            ConnectionMessage::Response(data) => {
                info!("response data: {:?}", data);

                let sender = manager.remove_response_data(data.local_seq.clone());
                if let Some(sender) = sender {
                    sender.send(data).ok();
                }
            }
        }
    }
}
